home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Direct3D / EnvMapping / SphereMap / spheremap.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  16.7 KB  |  516 lines

  1. //-----------------------------------------------------------------------------
  2. // File: SphereMap.cpp
  3. //
  4. // Desc: Example code showing how to use sphere-mapping in D3D, using generated 
  5. //       texture coordinates.
  6. //
  7. // Copyright (c) 1997-2001 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <tchar.h>
  11. #include <math.h>
  12. #include <stdio.h>
  13. #include <D3DX8.h>
  14. #include "D3DApp.h"
  15. #include "D3DFile.h"
  16. #include "D3DFont.h"
  17. #include "D3DUtil.h"
  18. #include "DXUtil.h"
  19.  
  20.  
  21. //-----------------------------------------------------------------------------
  22. // Name: g_szEffect
  23. // Desc: String containing effect used to render shiny teapot.
  24. //-----------------------------------------------------------------------------
  25.  
  26. const char g_szEffect[] = 
  27.  
  28.     "texture texSphereMap;\n"
  29.     "matrix matWorld;\n"
  30.     "matrix matViewProject;\n"
  31.     "vector vecPosition;\n"
  32.  
  33.  
  34.     "technique Sphere\n"
  35.     "{\n"
  36.         "pass P0\n"
  37.         "{\n"
  38.  
  39.             // Vertex state
  40.             "VertexShader =\n"
  41.                 "decl\n"
  42.                 "{\n"
  43.                     "float v0[3];\n"  // position
  44.                     "float v1[3];\n"  // normal
  45.                 "}\n"
  46.                 "asm\n"
  47.                 "{\n"
  48.                     "vs.1.0\n"
  49.                     "def c64, 0.25f, 0.5f, 1.0f, -1.0f\n"
  50.         
  51.                     // r0: camera-space position
  52.                     // r1: camera-space normal
  53.                     // r2: camera-space vertex-eye vector
  54.                     // r3: camera-space reflection vector
  55.                     // r4: texture coordinates
  56.  
  57.                     // Transform position and normal into camera-space
  58.                     "m4x4 r0, v0, c0\n"
  59.                     "m3x3 r1, v1, c0\n"
  60.  
  61.                     // Compute normalized view vector
  62.                     "add r2, c8, -r0\n"
  63.                     "dp3 r3, r2, r2\n"
  64.                     "rsq r3, r3\n"
  65.                     "mul r2, r2, r3\n"
  66.  
  67.                     // Compute camera-space reflection vector
  68.                     "dp3 r3, r1, r2\n"
  69.                     "mul r1, r1, r3\n"
  70.                     "add r1, r1, r1\n"
  71.                     "add r3, r1, -r2\n"
  72.  
  73.                     // Compute sphere-map texture coords
  74.                     "mad r4.w, -r3.z, c64.y, c64.y\n"
  75.                     "rsq r4, r4\n"
  76.                     "mul r4, r3, r4\n"
  77.                     "mad r4, r4, c64.x, c64.y\n"
  78.  
  79.                     // Project position
  80.                     "m4x4 oPos, r0, c4\n"
  81.                     "mul oT0.xy, r4.xy, c64.zw\n"
  82.                     "mov oT0.zw, c64.z\n"
  83.                 "};\n"
  84.  
  85.             "VertexShaderConstant4[0] = <matWorld>;\n"
  86.             "VertexShaderConstant4[4] = <matViewProject>;\n"
  87.             "VertexShaderConstant1[8] = <vecPosition>;\n"
  88.  
  89.             // Pixel state
  90.             "Texture[0] = <texSphereMap>;\n"
  91.             "AddressU[0] = Wrap;\n"
  92.             "AddressV[0] = Wrap;\n"
  93.             "MinFilter[0] = Linear;\n"
  94.             "MagFilter[0] = Linear;\n"
  95.             "ColorOp[0] = SelectArg1;\n"
  96.             "ColorArg1[0] = Texture;\n"
  97.         "}\n"
  98.     "}\n";
  99.  
  100. const UINT g_cchEffect = sizeof(g_szEffect) - 1;
  101.  
  102.  
  103.  
  104.  
  105. //-----------------------------------------------------------------------------
  106. // Name: struct ENVMAPPEDVERTEX
  107. // Desc: D3D vertex type for environment-mapped objects
  108. //-----------------------------------------------------------------------------
  109. struct ENVMAPPEDVERTEX
  110. {
  111.     D3DXVECTOR3 p; // Position
  112.     D3DXVECTOR3 n; // Normal
  113. };
  114.  
  115. #define D3DFVF_ENVMAPVERTEX ( D3DFVF_XYZ | D3DFVF_NORMAL )
  116.  
  117.  
  118.  
  119. //-----------------------------------------------------------------------------
  120. // Name: class CMyD3DApplication
  121. // Desc: Application class. The base class (CD3DApplication) provides the 
  122. //       generic functionality needed in all Direct3D samples. CMyD3DApplication 
  123. //       adds functionality specific to this sample program.
  124. //-----------------------------------------------------------------------------
  125. class CMyD3DApplication : public CD3DApplication
  126. {
  127.     BOOL m_bCapture;
  128.  
  129.     D3DXMATRIX m_matProject;
  130.     D3DXMATRIX m_matView;
  131.     D3DXMATRIX m_matWorld;
  132.     D3DXMATRIX m_matTrackBall;
  133.  
  134.     CD3DFont* m_pFont;
  135.     CD3DMesh* m_pShinyTeapot;
  136.     CD3DMesh* m_pSkyBox;
  137.  
  138.     ID3DXEffect* m_pEffect;
  139.     IDirect3DTexture8* m_pSphereMap;
  140.  
  141. protected:
  142.     HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT );
  143.     HRESULT OneTimeSceneInit();
  144.     HRESULT InitDeviceObjects();
  145.     HRESULT RestoreDeviceObjects();
  146.     HRESULT InvalidateDeviceObjects();
  147.     HRESULT DeleteDeviceObjects();
  148.     HRESULT Render();
  149.     HRESULT FrameMove();
  150.     HRESULT FinalCleanup();
  151.  
  152. public:
  153.     LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
  154.  
  155.     CMyD3DApplication();
  156. };
  157.  
  158.  
  159.  
  160.  
  161. //-----------------------------------------------------------------------------
  162. // Name: WinMain()
  163. // Desc: Entry point to the program. Initializes everything, and goes into a
  164. //       message-processing loop. Idle time is used to render the scene.
  165. //-----------------------------------------------------------------------------
  166. INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
  167. {
  168.     CMyD3DApplication d3dApp;
  169.  
  170.     if( FAILED( d3dApp.Create( hInst ) ) )
  171.         return 0;
  172.  
  173.     return d3dApp.Run();
  174. }
  175.  
  176.  
  177.  
  178.  
  179. //-----------------------------------------------------------------------------
  180. // Name: CMyD3DApplication()
  181. // Desc: Application constructor. Sets attributes for the app.
  182. //-----------------------------------------------------------------------------
  183. CMyD3DApplication::CMyD3DApplication()
  184. {
  185.     m_strWindowTitle    = _T("SphereMap: Environment Mapping Technique");
  186.     m_bUseDepthBuffer   = TRUE;
  187.     m_bCapture          = FALSE;
  188.  
  189.     m_pFont             = NULL;
  190.     m_pShinyTeapot      = NULL;
  191.     m_pSkyBox           = NULL;
  192.     
  193.     m_pEffect           = NULL;
  194.     m_pSphereMap        = NULL;
  195. }
  196.  
  197.  
  198.  
  199.  
  200. //-----------------------------------------------------------------------------
  201. // Name: OneTimeSceneInit()
  202. // Desc: Called during initial app startup, this function performs all the
  203. //       permanent initialization.
  204. //-----------------------------------------------------------------------------
  205. HRESULT CMyD3DApplication::OneTimeSceneInit()
  206. {
  207.     D3DXMatrixIdentity( &m_matWorld );
  208.  
  209.     m_pFont        = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
  210.     m_pShinyTeapot = new CD3DMesh();
  211.     m_pSkyBox      = new CD3DMesh();
  212.     
  213.     if( !m_pFont || !m_pShinyTeapot || !m_pSkyBox )
  214.         return E_OUTOFMEMORY;
  215.  
  216.     D3DXMatrixIdentity( &m_matTrackBall );
  217.     D3DXMatrixTranslation( &m_matView, 0.0f, 0.0f, 3.0f );
  218.  
  219.     return S_OK;
  220. }
  221.  
  222.  
  223.  
  224.  
  225. //-----------------------------------------------------------------------------
  226. // Name: FrameMove()
  227. // Desc: Called once per frame, the call is the entry point for animating
  228. //       the scene.
  229. //-----------------------------------------------------------------------------
  230. HRESULT CMyD3DApplication::FrameMove()
  231. {
  232.     // When the window has focus, let the mouse adjust the camera view
  233.     if( m_bCapture )
  234.     {
  235.         D3DXMATRIX matCursor;
  236.         D3DXQUATERNION qCursor = D3DUtil_GetRotationFromCursor( m_hWnd );
  237.         D3DXMatrixRotationQuaternion( &matCursor, &qCursor );
  238.         D3DXMatrixMultiply( &m_matView, &m_matTrackBall, &matCursor );
  239.  
  240.         D3DXMATRIX matTrans;
  241.         D3DXMatrixTranslation( &matTrans, 0.0f, 0.0f, 3.0f );
  242.         D3DXMatrixMultiply( &m_matView, &m_matView, &matTrans );
  243.     }
  244.     else
  245.     {
  246.         D3DXMATRIX matRotation;
  247.         D3DXMatrixRotationY( &matRotation, -m_fElapsedTime );
  248.         D3DXMatrixMultiply( &m_matWorld, &m_matWorld, &matRotation );
  249.     }
  250.  
  251.     return S_OK;
  252. }
  253.  
  254.  
  255.  
  256. //-----------------------------------------------------------------------------
  257. // Name: Render()
  258. // Desc: Called once per frame, the call is the entry point for 3d
  259. //       rendering. This function sets up render states, clears the
  260. //       viewport, and renders the scene.
  261. //-----------------------------------------------------------------------------
  262. HRESULT CMyD3DApplication::Render()
  263. {
  264.     // Begin the scene
  265.     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
  266.     {
  267.         // Render the Skybox
  268.         {
  269.             D3DXMATRIX matWorld;
  270.             D3DXMatrixScaling( &matWorld, 10.0f, 10.0f, 10.0f );
  271.  
  272.             D3DXMATRIX matView(m_matView);
  273.             matView._41 = matView._42 = matView._43 = 0.0f;
  274.  
  275.             m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  276.             m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  277.             m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProject );
  278.  
  279.             m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  280.             m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_SELECTARG1 );
  281.             m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
  282.             m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
  283.             m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSU,  D3DTADDRESS_MIRROR );
  284.             m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ADDRESSV,  D3DTADDRESS_MIRROR );
  285.  
  286.             // Always pass Z-test, so we can avoid clearing color and depth buffers
  287.             m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_ALWAYS );
  288.             m_pSkyBox->Render( m_pd3dDevice );
  289.             m_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
  290.         }
  291.  
  292.  
  293.         // Render the environment-mapped ShinyTeapot
  294.         {
  295.             // Set transform state
  296.             D3DXMATRIX matViewProject;
  297.             D3DXMatrixMultiply( &matViewProject, &m_matView, &m_matProject );
  298.  
  299.             D3DXMATRIX matViewInv;
  300.             D3DXMatrixInverse( &matViewInv, NULL, &m_matView );
  301.             D3DXVECTOR4 vecPosition( matViewInv._41, matViewInv._42, matViewInv._43, 1.0f );
  302.  
  303.  
  304.             m_pEffect->SetMatrix( "matWorld", &m_matWorld );
  305.             m_pEffect->SetMatrix( "matViewProject", &matViewProject );
  306.             m_pEffect->SetVector( "vecPosition", &vecPosition );
  307.  
  308.  
  309.             // Draw teapot
  310.             LPDIRECT3DVERTEXBUFFER8 pVB;
  311.             LPDIRECT3DINDEXBUFFER8 pIB;
  312.  
  313.             m_pShinyTeapot->m_pLocalMesh->GetVertexBuffer( &pVB );
  314.             m_pShinyTeapot->m_pLocalMesh->GetIndexBuffer( &pIB );
  315.  
  316.             m_pd3dDevice->SetStreamSource( 0, pVB, sizeof(ENVMAPPEDVERTEX) );
  317.             m_pd3dDevice->SetIndices( pIB, 0 );
  318.  
  319.             UINT uPasses;
  320.             m_pEffect->Begin( &uPasses, 0 );
  321.  
  322.             for( UINT iPass = 0; iPass < uPasses; iPass++ )
  323.             {
  324.                 m_pEffect->Pass( iPass );
  325.  
  326.                 m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 
  327.                     0, m_pShinyTeapot->m_pLocalMesh->GetNumVertices(),
  328.                     0, m_pShinyTeapot->m_pLocalMesh->GetNumFaces() );
  329.  
  330.             }
  331.  
  332.             m_pEffect->End();
  333.  
  334.             SAFE_RELEASE( pVB );
  335.             SAFE_RELEASE( pIB );
  336.         }
  337.  
  338.  
  339.         // Output statistics
  340.         m_pFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats );
  341.         m_pFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats );
  342.  
  343.  
  344.         // End the scene.
  345.         m_pd3dDevice->EndScene();
  346.     }
  347.  
  348.     return S_OK;
  349. }
  350.  
  351.  
  352.  
  353.  
  354. //-----------------------------------------------------------------------------
  355. // Name: InitDeviceObjects()
  356. // Desc: Initialize scene objects.
  357. //-----------------------------------------------------------------------------
  358. HRESULT CMyD3DApplication::InitDeviceObjects()
  359. {
  360.     // Load the file objects
  361.     if( FAILED( m_pShinyTeapot->Create( m_pd3dDevice, _T("teapot.x") ) ) )
  362.         return D3DAPPERR_MEDIANOTFOUND;
  363.     if( FAILED( m_pSkyBox->Create( m_pd3dDevice, _T("lobby_skybox.x") ) ) )
  364.         return D3DAPPERR_MEDIANOTFOUND;
  365.     if( FAILED( D3DUtil_CreateTexture( m_pd3dDevice, _T("spheremap.bmp"), &m_pSphereMap ) ) )
  366.         return D3DAPPERR_MEDIANOTFOUND;
  367.  
  368.     // Set mesh properties
  369.     m_pShinyTeapot->SetFVF( m_pd3dDevice, D3DFVF_ENVMAPVERTEX );
  370.  
  371.     // Restore the device-dependent objects
  372.     m_pFont->InitDeviceObjects( m_pd3dDevice );
  373.  
  374.     // Create Effect object
  375.     if( FAILED( D3DXCreateEffect( m_pd3dDevice, g_szEffect, g_cchEffect, &m_pEffect, NULL ) ) )
  376.         return E_FAIL;
  377.  
  378.     return S_OK;
  379. }
  380.  
  381.  
  382.  
  383.  
  384. //-----------------------------------------------------------------------------
  385. // Name: RestoreDeviceObjects()
  386. // Desc: Restore device-memory objects and state after a device is created or
  387. //       resized.
  388. //-----------------------------------------------------------------------------
  389. HRESULT CMyD3DApplication::RestoreDeviceObjects()
  390. {
  391.     // InitDeviceObjects for file objects (build textures and vertex buffers)
  392.     m_pShinyTeapot->RestoreDeviceObjects( m_pd3dDevice );
  393.     m_pSkyBox->RestoreDeviceObjects( m_pd3dDevice );
  394.     m_pFont->RestoreDeviceObjects();
  395.     m_pEffect->OnResetDevice();
  396.     m_pEffect->SetTexture( "texSphereMap", m_pSphereMap );
  397.  
  398.     // Set the transform matrices
  399.     FLOAT fAspect = (FLOAT) m_d3dsdBackBuffer.Width / (FLOAT) m_d3dsdBackBuffer.Height;
  400.     D3DXMatrixPerspectiveFovLH( &m_matProject, D3DX_PI * 0.4f, fAspect, 0.5f, 100.0f );
  401.     return S_OK;
  402. }
  403.  
  404.  
  405.  
  406.  
  407. //-----------------------------------------------------------------------------
  408. // Name: InvalidateDeviceObjects()
  409. // Desc: Called when the device-dependent objects are about to be lost.
  410. //-----------------------------------------------------------------------------
  411. HRESULT CMyD3DApplication::InvalidateDeviceObjects()
  412. {
  413.     m_pShinyTeapot->InvalidateDeviceObjects();
  414.     m_pSkyBox->InvalidateDeviceObjects();
  415.     m_pFont->InvalidateDeviceObjects();
  416.  
  417.     if(m_pEffect)
  418.         m_pEffect->OnLostDevice();
  419.  
  420.     return S_OK;
  421. }
  422.  
  423.  
  424.  
  425.  
  426. //-----------------------------------------------------------------------------
  427. // Name: DeleteDeviceObjects()
  428. // Desc: Called when the app is exiting, or the device is being changed,
  429. //       this function deletes any device dependent objects.
  430. //-----------------------------------------------------------------------------
  431. HRESULT CMyD3DApplication::DeleteDeviceObjects()
  432. {
  433.     m_pFont->DeleteDeviceObjects();
  434.     m_pShinyTeapot->Destroy();
  435.     m_pSkyBox->Destroy();
  436.  
  437.     SAFE_RELEASE( m_pSphereMap );
  438.     SAFE_RELEASE( m_pEffect );
  439.     return S_OK;
  440. }
  441.  
  442.  
  443.  
  444.  
  445. //-----------------------------------------------------------------------------
  446. // Name: FinalCleanup()
  447. // Desc: Called before the app exits, this function gives the app the chance
  448. //       to cleanup after itself.
  449. //-----------------------------------------------------------------------------
  450. HRESULT CMyD3DApplication::FinalCleanup()
  451. {
  452.     SAFE_DELETE( m_pFont );
  453.     SAFE_DELETE( m_pShinyTeapot );
  454.     SAFE_DELETE( m_pSkyBox );
  455.  
  456.     return S_OK;
  457. }
  458.  
  459.  
  460.  
  461.  
  462. //-----------------------------------------------------------------------------
  463. // Name: ConfirmDevice()
  464. // Desc: Called during device intialization, this code checks the device
  465. //       for some minimum set of capabilities
  466. //-----------------------------------------------------------------------------
  467. HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS8* pCaps, DWORD dwBehavior,
  468.                                           D3DFORMAT Format )
  469. {
  470.     if( !(dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING) &&
  471.         !(pCaps->VertexShaderVersion >= D3DVS_VERSION(1, 0)) )
  472.     {
  473.         return E_FAIL;
  474.     }
  475.  
  476.     return S_OK;
  477. }
  478.  
  479.  
  480. //-----------------------------------------------------------------------------
  481. // Name: MsgProc()
  482. // Desc: Message proc function to handle key and menu input
  483. //-----------------------------------------------------------------------------
  484. LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
  485.                                     LPARAM lParam )
  486. {
  487.     // Capture mouse when clicked
  488.     if( WM_LBUTTONDOWN == uMsg )
  489.     {
  490.         D3DXMATRIX matCursor;
  491.         D3DXQUATERNION qCursor = D3DUtil_GetRotationFromCursor( m_hWnd );
  492.         D3DXMatrixRotationQuaternion( &matCursor, &qCursor );
  493.         D3DXMatrixTranspose( &matCursor, &matCursor );
  494.         D3DXMatrixMultiply( &m_matTrackBall, &m_matTrackBall, &matCursor );
  495.  
  496.         SetCapture( m_hWnd );
  497.         m_bCapture = TRUE;
  498.         return 0;
  499.     }
  500.  
  501.     if( WM_LBUTTONUP == uMsg )
  502.     {
  503.         D3DXMATRIX matCursor;
  504.         D3DXQUATERNION qCursor = D3DUtil_GetRotationFromCursor( m_hWnd );
  505.         D3DXMatrixRotationQuaternion( &matCursor, &qCursor );
  506.         D3DXMatrixMultiply( &m_matTrackBall, &m_matTrackBall, &matCursor );
  507.  
  508.         ReleaseCapture();
  509.         m_bCapture = FALSE;
  510.         return 0;
  511.     }
  512.  
  513.     // Pass remaining messages to default handler
  514.     return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam );
  515. }
  516.